package com.walle.ak47.commons.utils.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;

public class JsonUtil {

	public static <T> T toObject(String json, Class<T> cls,
			boolean isConvertDate, boolean isCheck, String fieldNames)
			throws JsonException {

		if (StringUtils.isEmpty(json))
			return null;

		String[] fileds = StringUtils.split(fieldNames, ",");

		T result = null;
		if (isConvertDate)
			result = toObjectForDate(json, cls);
		else
			result = toObject(json, cls);

		if (result == null)
			return null;

		if (isCheck) {
			Map<String, Object> srcJsonMap = JsonUtil.toMap(json);
			String resultJson = JsonUtil.toJSon(result);
			Map<String, Object> resultJsonMap = JsonUtil.toMap(resultJson);

			Iterator<String> iter = srcJsonMap.keySet().iterator();
			while (iter.hasNext()) {
				String attrName = iter.next();
				if (resultJsonMap.get(attrName) == null)
					throw new JsonException("类型中不存在名字为" + attrName + "的字段或属性");

				if (fileds != null && fileds.length > 0) {
					boolean isFind = false;
					for (int i = 0; i < fileds.length; i++) {
						if (attrName.equals(fileds[i])) {
							isFind = true;
							break;
						}

					}
					if (!isFind)
						throw new JsonException("类型中不存在名字为" + attrName
								+ "的字段或属性");
				}
			}
		}

		return result;
	}

	public static <T> T toObject(String json, Class<T> cls,
			boolean isConvertDate, boolean isCheck) throws JsonException {
		if (StringUtils.isEmpty(json))
			return null;

		T result = null;
		if (isConvertDate)
			result = toObjectForDate(json, cls);
		else
			result = toObject(json, cls);

		if (result == null)
			return null;

		if (isCheck) {
			Map<String, Object> srcJsonMap = JsonUtil.toMap(json);
			String resultJson = JsonUtil.toJSon(result);
			Map<String, Object> resultJsonMap = JsonUtil.toMap(resultJson);

			Iterator<String> iter = srcJsonMap.keySet().iterator();
			while (iter.hasNext()) {
				String attrName = iter.next();
				if (resultJsonMap.get(attrName) == null)
					throw new JsonException("类型中不存在名字为" + attrName + "的字段或属性");
			}
		}

		return result;
	}

	public static <T> T toObject(String json, Class<T> cls, boolean isCheck)
			throws JsonException {
		if (StringUtils.isEmpty(json))
			return null;

		T result = toObject(json, cls);

		if (result == null)
			return null;

		if (isCheck) {
			Map<String, Object> srcJsonMap = JsonUtil.toMap(json);
			String resultJson = JsonUtil.toJSon(result);
			Map<String, Object> resultJsonMap = JsonUtil.toMap(resultJson);

			Iterator<String> iter = srcJsonMap.keySet().iterator();
			while (iter.hasNext()) {
				String attrName = iter.next();
				if (resultJsonMap.get(attrName) == null)
					throw new JsonException("类型中不存在名字为" + attrName + "的字段或属性");
			}
		}

		return result;
	}

	/**
	 * 
	 * @param json
	 * @param cls
	 * @param format
	 * @return
	 * @throws JsonException
	 */
	public static <T> T toObjectForDate(String json, Class<T> cls)
			throws JsonException {
		T t = null;

		boolean isConvertJsonObject = false;
		try {
			Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls()
					.setDateFormat("'Date'(yyyy-MM-dd HH:mm:ss)").create();
			t = gson.fromJson(json, cls);
			isConvertJsonObject = true;
		} catch (JsonSyntaxException ex) {
		}

		if (!isConvertJsonObject) {
			try {
				Gson gson = new GsonBuilder().setPrettyPrinting()
						.setDateFormat("yyyy-MM-dd HH:mm:ss").create();
				t = gson.fromJson(json, cls);
				isConvertJsonObject = true;
			} catch (JsonSyntaxException ex) {
			}
		}

		if (!isConvertJsonObject) {
			try {
				Gson gson = new GsonBuilder().setPrettyPrinting()
						.setDateFormat("yyyy-MM-dd").create();
				t = gson.fromJson(json, cls);
				isConvertJsonObject = true;
			} catch (JsonSyntaxException ex) {
			}
		}

		if (!isConvertJsonObject)
			throw new JsonException("无效的json格式");

		return t;

	}

	public static <T> T toObject(String json, Class<T> cls)
			throws JsonException {
		T t = null;
		try {
			Gson gson = new GsonBuilder().setPrettyPrinting().create();
			t = gson.fromJson(json, cls);
		} catch (Exception ex) {
			throw new JsonException("查询条件不符合json格式");
		}

		return t;
	}

	public static String toJSon(Object object) {

		Gson gson = new GsonBuilder().create();
		String str = gson.toJson(object);
		return str;
	}

	public static String toFormatJSon(Object object) {

		Gson gson = new GsonBuilder().setPrettyPrinting().create();
		String str = gson.toJson(object);
		return str;
	}

	/**
	 * 获取JsonObject
	 * 
	 * @param json
	 * @return
	 */
	public static JsonObject parseJson(String json) {
		JsonParser parser = new JsonParser();
		JsonObject jsonObj = parser.parse(json).getAsJsonObject();
		return jsonObj;
	}

	/**
	 * 根据json字符串返回Map对象
	 * 
	 * @param json
	 * @return
	 */
	public static Map<String, Object> toMap(String json) {
		return toMap(parseJson(json));
	}

	/**
	 * 将JSONObjec对象转换成Map-List集合
	 * 
	 * @param json
	 * @return
	 */
	public static Map<String, Object> toMap(JsonObject json) {
		Map<String, Object> map = new HashMap<String, Object>();
		Set<Entry<String, JsonElement>> entrySet = json.entrySet();
		for (Iterator<Entry<String, JsonElement>> iter = entrySet.iterator(); iter
				.hasNext();) {
			Entry<String, JsonElement> entry = iter.next();
			String key = entry.getKey();
			Object value = entry.getValue();
			if (value instanceof JsonArray)
				map.put((String) key, toList((JsonArray) value));
			else if (value instanceof JsonObject)
				map.put((String) key, toMap((JsonObject) value));
			else
				map.put((String) key, value);
		}
		return map;
	}

	/**
	 * 将JSONArray对象转换成List集合
	 * 
	 * @param json
	 * @return
	 */
	public static List<Object> toList(JsonArray json) {
		List<Object> list = new ArrayList<Object>();
		for (int i = 0; i < json.size(); i++) {
			Object value = json.get(i);
			if (value instanceof JsonArray) {
				list.add(toList((JsonArray) value));
			} else if (value instanceof JsonObject) {
				list.add(toMap((JsonObject) value));
			} else {
				list.add(value);
			}
		}
		return list;
	}
}
